Pass by Reference Error?

Hi,

I have a problem that I fixed but I can't figure out why. I wrote the following little function:

bool readLine(string p_sIn, string &sOut, int &p_iStart) {
        // updates sOut to be  everything from index "start" to the next newline.
        // updates start to be the index of the first character following the newline.
        // returns true if sOut is valid. sOut will be valid as long as p_iStart is
        // a valid index within p_sIn
        
        //print "readLine "
        
        if ((p_iStart < 0) || (p_iStart > (length(p_sIn) - 1))) {
                return false;
        }
        
        int iEnd = p_iStart + 1;
        while ((iEnd < length(p_sIn)) && (p_sIn[iEnd] != '\n')) {
                iEnd++;
        }

        sOut = p_sIn[p_iStart:(iEnd - 1)];
        p_iStart = iEnd + 1;
        return true;
                
}

string S_INPUT = "AAA-97
AAA-98
AAA-99
AAA-100"

string sReqNo = null;
int iIndex = 0;
while (readLine(S_INPUT, sReqNo, iIndex)) {
        print sReqNo " starts at index " iIndex ".\n";
}

(that last part is just test code)

But the function fails as follows:

-E- DXL: <Line:18> incorrect arguments for (by)
-E- DXL: <Line:18> incorrect arguments for ([)
-E- DXL: <Line:18> incorrect arguments for (=)
-I- DXL: All done. Errors reported: 3. Warnings reported: 0.

I can get the function to work by doing the following:

bool readLine(string p_sIn, string &sOut, int &p_iStart) {
        // updates sOut to be  everything from index "start" to the next newline.
        // updates start to be the index of the first character following the newline.
        // returns true if sOut is valid. sOut will be valid as long as p_iStart is
        // a valid index within p_sIn
        
        //print "readLine "
        
        if ((p_iStart < 0) || (p_iStart > (length(p_sIn) - 1))) {
                return false;
        }
        
        int iEnd = p_iStart + 1;
        while ((iEnd < length(p_sIn)) && (p_sIn[iEnd] != '\n')) {
                iEnd++;
        }
        print "iStart = " p_iStart ", "
        print "iEnd = " iEnd ", ";
        int i, j;  // wtf
        i = p_iStart;
        j = iEnd;
        sOut = p_sIn[i:(j-1)];
        p_iStart = iEnd + 1;
        return true;
                
}

This seems stupid. But then again I don't really know what I'm doing. Can anyone see an error with how I'm passing by reference? I assume I'm doing something wrong there.


JSRowland - Mon Nov 28 19:51:16 EST 2016

Re: Pass by Reference Error?
Adamarla - Tue Nov 29 06:38:36 EST 2016

bool readLine(string p_sIn, string &rsOut, int &rp_iStart) {

        int p_iStart = rp_iStart // Dereference

        // updates sOut to be  everything from index "start" to the next newline.
        // updates start to be the index of the first character following the newline.
        // returns true if sOut is valid. sOut will be valid as long as p_iStart is
        // a valid index within p_sIn

        //print "readLine "

        if ((p_iStart < 0) || (p_iStart > (length(p_sIn) - 1))) {
                return false;
        }

        int iEnd = p_iStart + 1;
        while ((iEnd < length(p_sIn)) && (p_sIn[iEnd] != '\n')) {
                iEnd++;
        }

        // Set return values
        rsOut = p_sIn[p_iStart:(iEnd - 1)];
        rp_iStart = iEnd + 1;
        return true;

}

string S_INPUT = "AAA-97
AAA-98
AAA-99
AAA-100"

string sReqNo = null;
int iIndex = 0;
while (readLine(S_INPUT, sReqNo, iIndex)) {
        print sReqNo " starts at index " iIndex ".\n";
}

You need to "Dereference"  your referenced args and use the dereferenced variables for processing.

Then use the "Reference" arg to set the return values.

 

-Adam

Re: Pass by Reference Error?
JSRowland - Tue Nov 29 10:50:37 EST 2016

Adamarla - Tue Nov 29 06:38:36 EST 2016

bool readLine(string p_sIn, string &rsOut, int &rp_iStart) {

        int p_iStart = rp_iStart // Dereference

        // updates sOut to be  everything from index "start" to the next newline.
        // updates start to be the index of the first character following the newline.
        // returns true if sOut is valid. sOut will be valid as long as p_iStart is
        // a valid index within p_sIn

        //print "readLine "

        if ((p_iStart < 0) || (p_iStart > (length(p_sIn) - 1))) {
                return false;
        }

        int iEnd = p_iStart + 1;
        while ((iEnd < length(p_sIn)) && (p_sIn[iEnd] != '\n')) {
                iEnd++;
        }

        // Set return values
        rsOut = p_sIn[p_iStart:(iEnd - 1)];
        rp_iStart = iEnd + 1;
        return true;

}

string S_INPUT = "AAA-97
AAA-98
AAA-99
AAA-100"

string sReqNo = null;
int iIndex = 0;
while (readLine(S_INPUT, sReqNo, iIndex)) {
        print sReqNo " starts at index " iIndex ".\n";
}

You need to "Dereference"  your referenced args and use the dereferenced variables for processing.

Then use the "Reference" arg to set the return values.

 

-Adam

Thanks. I don't know how I never learned that. Is that normal for C-family languages?

Why didn't you have to dereference p_sIn in

rsOut = p_sIn[p_iStart:(iEnd - 1)];

?

Re: Pass by Reference Error?
Adamarla - Tue Nov 29 12:41:57 EST 2016

JSRowland - Tue Nov 29 10:50:37 EST 2016

Thanks. I don't know how I never learned that. Is that normal for C-family languages?

Why didn't you have to dereference p_sIn in

rsOut = p_sIn[p_iStart:(iEnd - 1)];

?

The arg p_sIn in is not a reference (no & prefix).

You only assign to rsOut, so you don't need to dereference that either. You should if you read it though.

It's one of those DXL things that can mess you up and cause hours of bug hunting.

The "value" the reference recieves, is the address of the variable. It's tough to know how it will be interpreted when passing it on to other functions.

For example null() will just see the address and determine it is not zero:

 

void isNull(int &ri) {
        print null(ri)
        int i = ri
        print null(i)
}

int i = 0
print null(i)
isNull(i)
i = 123
print null(i)
isNull(i)

 

-Adam

Re: Pass by Reference Error?
Mathias Mamsch - Wed Nov 30 03:38:25 EST 2016

Adamarla - Tue Nov 29 12:41:57 EST 2016

The arg p_sIn in is not a reference (no & prefix).

You only assign to rsOut, so you don't need to dereference that either. You should if you read it though.

It's one of those DXL things that can mess you up and cause hours of bug hunting.

The "value" the reference recieves, is the address of the variable. It's tough to know how it will be interpreted when passing it on to other functions.

For example null() will just see the address and determine it is not zero:

 

void isNull(int &ri) {
        print null(ri)
        int i = ri
        print null(i)
}

int i = 0
print null(i)
isNull(i)
i = 123
print null(i)
isNull(i)

 

-Adam

Just for a technical explanation: 

the ..by operator  "a:b" is defined as: 

From the arguments you can see, that it takes two times the _x parameter, that means you can pass any argument inside, but both arguments must have the same type. In your case you have been passing int& and int inside, which was not accepted. Two integer references should work (DXL should automatically dereference) and two integers should also work. Little test:

string s = "abcdefghijlkmnopqr"; 
int a = 10; 
int b = 12;

int &ra = a; 
int &rb = b;

print s[a:b] "\n"   // accepted, works
print s[ra:rb] "\n" // accepted syntax, does not work

So yes as Adam said, that can make your day very bad. You are lucky, you tried the non working variant with different types first :-)

Regards, Mathias